﻿using KBEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class RoomOpCard : MonoBehaviour
{
	// Use this for initialization
	void Start()
	{
		KBEngine.Event.registerOut("onCurStateChanged", this, "onCurStateChanged");
		KBEngine.Event.registerOut("onEnterWorld", this, "onEnterWorld");
		KBEngine.Event.registerOut("onEnterSpace", this, "onEnterSpace");
		KBEngine.Event.registerOut("onRoomIDChanged", this, "onRoomIDChanged");
		KBEngine.Event.registerOut("onContainerPropChanged", this, "onContainerPropChanged");

		KBEngine.Event.registerOut("onCell2ClientMsg", this, "onRoomNetMsg");

		onEnterSpace(KBEngineApp.app.player());
		onRoomIDChanged(0);
	}

	public void onRoomIDChanged(UInt32 oldVal)
	{
		Account acc = KBEngineApp.app.player() as Account;
		transform.Find("txt_room_id").GetComponent<Text>().text = Convert.ToString(acc.roomID);
	}

	void OnDestroy()
	{
		KBEngine.Event.deregisterOut(this);
	}

	public void onContainerPropChanged(Int32 entityID, string propName, object oldVal, int changeType)
	{
		switch (propName)
		{
			case "handCards":
				onHandCardsChanged(entityID);
				break;
		}

	}

	class CardCmp : IComparer<object>
	{
		public int Compare(object x, object y)
		{
			Int32 x1 = Convert.ToInt32(x) / 100;
			Int32 x2 = Convert.ToInt32(x) % 100;

			Int32 y1 = Convert.ToInt32(y) / 100;
			Int32 y2 = Convert.ToInt32(y) % 100;

			if(x2 != y2)
			{
				return x2 < y2 ? 1 : -1;
			}

			if (x1 != y1)
			{
				return x1 > y1 ? 1 : -1;
			}

			return 0;
		}
	}

	private void onHandCardsChanged(int entityID)
	{
		Account acc = KBEngineApp.app.player() as Account;
		if (acc.id != entityID)
		{
			return;
		}

		Image imgCards = transform.Find("img_cards").GetComponent<Image>();
		Dictionary<uint, Image> cloneImgs = imgCards.transform.GetComponent<CustomData>().objData as Dictionary<uint, Image>;
		if (cloneImgs != null)
		{
			foreach (var imgPair in cloneImgs)
			{
				Destroy(imgPair.Value.gameObject);
			}
		}
		imgCards.transform.GetComponent<CustomData>().objData = new Dictionary<uint, Image>();
		cloneImgs = imgCards.transform.GetComponent<CustomData>().objData as Dictionary<uint, Image>;

		Image imgCard = imgCards.transform.Find("img_card").GetComponent<Image>();

		Dictionary<object, object> cards = acc.GetContainerProp("handCards") as Dictionary<object, object>;

		var sortCards = cards.OrderBy(p => p.Key, new CardCmp());
		int i = 0;
		foreach (var cardPair in sortCards)
		{
			uint showCard = Convert.ToUInt32(cardPair.Key);
			uint count = Convert.ToUInt32(cardPair.Value);
			Vector3 pos = new Vector3(imgCard.rectTransform.position.x + imgCard.rectTransform.rect.width / 4 * i, imgCard.rectTransform.position.y);
			Image imgCloneCard = Instantiate(imgCard, pos, new Quaternion(), imgCards.transform);
			imgCloneCard.gameObject.SetActive(true);

			imgCloneCard.transform.GetComponent<CustomData>().uint64Data = showCard;

			EventTrigger.Entry cardClickup = new EventTrigger.Entry();
			cardClickup.eventID = EventTriggerType.PointerUp;
			cardClickup.callback.AddListener(new UnityAction<BaseEventData>(
				(BaseEventData data) =>
				{
					onCardClickup(imgCloneCard);
				}
			));
			EventTrigger trigger = imgCloneCard.gameObject.AddComponent<EventTrigger>();
			trigger.triggers.Add(cardClickup);

			string spriteName = String.Format("card/{0:D0}", showCard);
			imgCloneCard.sprite = Resources.Load(spriteName, typeof(Sprite)) as Sprite;
			++i;

			cloneImgs[showCard] = imgCloneCard;
		}
	}

	public void onCardClickup(Image imgCloneCard)
	{
		Int64 isClick = imgCloneCard.transform.GetComponent<CustomData>().int64Data;
		isClick = isClick == 0 ? 1 : 0;
		imgCloneCard.transform.GetComponent<CustomData>().int64Data = isClick;

		float y = imgCloneCard.rectTransform.position.y;
		if (isClick == 0)
		{
			y -= imgCloneCard.rectTransform.rect.height / 4;
		}
		else
		{
			y += imgCloneCard.rectTransform.rect.height / 4;
		}

		imgCloneCard.rectTransform.position = new Vector3(imgCloneCard.rectTransform.position.x,
			y,
			imgCloneCard.rectTransform.position.z);
	}

	public void onNetPrepareResult(List<object> listMsg)
	{
		int errorID = Convert.ToInt32(listMsg[2]);
	}

	public void onEnterSpace(Entity entity)
	{
		onEnterWorld(entity);
	}

	public void onEnterWorld(Entity entity)
	{
		if (entity.className != "Account")
		{
			return;
		}

		Account enterAcc = entity as Account;
		Account acc = KBEngineApp.app.player() as Account;

		if (acc.id == enterAcc.id)
		{
			Dictionary<Int32, Entity> entities = KBEngineApp.app.entities;
			foreach (var entityPair in entities)
			{
				if (entityPair.Value.id == acc.id)
				{
					continue;
				}
				onEnterWorld(entityPair.Value);
			}
		}

		int enterAccIndex = 1;
		if (enterAcc.id != acc.id)
		{
			uint curSeatPos = acc.seatPos + 1 > ConstDef.PlayCardNeedPlayerNum ? 1 : acc.seatPos + 1;
			while (curSeatPos != acc.seatPos)
			{
				enterAccIndex++;

				if (curSeatPos == enterAcc.seatPos)
				{
					break;
				}

				curSeatPos = curSeatPos + 1 > ConstDef.PlayCardNeedPlayerNum ? 1 : curSeatPos + 1;
			}
		}

		Image imgPlayerInfo = transform.Find(String.Format("img_player_info{0:D0}", enterAccIndex)).GetComponent<Image>();
		imgPlayerInfo.transform.GetComponent<CustomData>().int64Data = enterAcc.id;

		imgPlayerInfo.transform.Find("txt_name").GetComponent<Text>().text = enterAcc.name;
		Sprite spHeadIcon = Resources.Load(String.Format("head/head{0:D0}", enterAcc.headIconID), typeof(Sprite)) as Sprite;
		imgPlayerInfo.transform.Find("img_head").GetComponent<Image>().sprite = spHeadIcon;

		onCurStateChanged(entity.id, 0);
	}

	private void playerPrepareOrNot(int entityID)
	{
		Account acc = KBEngineApp.app.player() as Account;

		Button btnPrepare = transform.Find("img_op_tips/btn_prepare").GetComponent<Button>();
		btnPrepare.onClick.RemoveAllListeners();
		btnPrepare.onClick.AddListener(
			() =>
			{
				btnPrepare.gameObject.SetActive(false);
				if (acc.curState != StateDef.RoomNoPlayWait)
				{
					return;
				}

				List<object> msg = new List<object>();
				msg.Add(MsgDef.CLIENT2CELL_ROOM_MSG);
				msg.Add(RoomDef.SUBMSG_PREPARE);
				KBEngine.Event.fireIn("sendCellMsg", msg);

				//IKernel.Instance().sendCellMsg(msg);
			}
		);

		btnPrepare.gameObject.SetActive(acc.curState == StateDef.RoomNoPlayWait ? true : false);
	}

	private void playerJiaopai(int entityID)
	{
		Account acc = KBEngineApp.app.player() as Account;

		Image imgJiaopai = transform.Find("img_op_tips/img_jiaopai").GetComponent<Image>();
		imgJiaopai.gameObject.SetActive(true);

		// 无返回值用 Action 
		// 有返回值用Func
		Action<int> jiaopaiOpResult = new Action<int>(
			(int isAgress) =>
			{
				imgJiaopai.gameObject.SetActive(false);

				List<object> msg = new List<object>();
				msg.Add(MsgDef.CLIENT2CELL_ROOM_MSG);
				msg.Add(acc.curState == StateDef.JiaoDizhu ? RoomDef.SUBMSG_JIAODIZHU : RoomDef.SUBMSG_QIANG_DIZHU);
				msg.Add(isAgress);
				KBEngine.Event.fireIn("sendCellMsg", msg);

				//IKernel.Instance().sendCellMsg(msg);
			}
		);

		Button btnAgress = imgJiaopai.transform.Find("btn_agres").GetComponent<Button>();
		btnAgress.transform.Find("Text").GetComponent<Text>().text = acc.curState == StateDef.JiaoDizhu ? "叫地主" : "抢地主";
		btnAgress.onClick.RemoveAllListeners();
		btnAgress.onClick.AddListener(
			() =>
			{
				jiaopaiOpResult(1);
			}
		);

		Button btnRefuse = imgJiaopai.transform.Find("btn_refuse").GetComponent<Button>();
		btnRefuse.transform.Find("Text").GetComponent<Text>().text = acc.curState == StateDef.JiaoDizhu ? "不叫" : "不抢";
		btnRefuse.onClick.RemoveAllListeners();
		btnRefuse.onClick.AddListener(
			() =>
			{
				jiaopaiOpResult(0);
			}
		);
	}

	private bool getWillPlayoutCards(out List<uint> willPlayoutShowCards, out int playoutCardType)
	{
		willPlayoutShowCards = new List<uint>();
		playoutCardType = 0;

		Account acc = KBEngineApp.app.player() as Account;
		if (acc.curState != StateDef.FirstPlayout && acc.curState != StateDef.FollowPlayout)
		{
			return false;
		}

		Image imgCards = transform.Find("img_cards").GetComponent<Image>();
		Dictionary<uint, Image> cloneImgs = imgCards.transform.GetComponent<CustomData>().objData as Dictionary<uint, Image>;
		if (cloneImgs == null)
		{
			return false;
		}

		foreach(var imgPair in cloneImgs)
		{
			Image imgCloneCard = imgPair.Value;
			Int64 isClick = imgCloneCard.transform.GetComponent<CustomData>().int64Data;
			if (isClick == 0)
			{
				continue;
			}

			uint showCard = imgPair.Key;
			willPlayoutShowCards.Add(showCard);
		}

		playoutCardType = PlayoutCardType.getShowCardsType(willPlayoutShowCards);
		if(playoutCardType == 0)
		{
			willPlayoutShowCards = new List<uint>();
		}

		return true;
	}

	private void playerPlayoutCard(int entityID)
	{
		Account acc = KBEngineApp.app.player() as Account;

		Image imgPlayoutTips = transform.Find("img_playout_tips").GetComponent<Image>();
		imgPlayoutTips.gameObject.SetActive(true);

		Action<int, List<uint>> playoutOpResult = new Action<int, List<uint>>(
			(int payoutCardType, List<uint> playoutCards)=>
			{
				imgPlayoutTips.gameObject.SetActive(false);

				List<object> msg = new List<object>();
				msg.Add(MsgDef.CLIENT2CELL_ROOM_MSG);
				msg.Add(RoomDef.SUBMSG_PALYOUT_CARD);
				msg.Add(payoutCardType);
				msg.Add(playoutCards.Count);
				for (int i = 0; i < playoutCards.Count; ++i)
				{
					msg.Add(playoutCards[i]);
				}
				KBEngine.Event.fireIn("sendCellMsg", msg);

				//IKernel.Instance().sendCellMsg(msg);
			}
		);

		Button btnReserve =  imgPlayoutTips.transform.Find("btn_reserve").GetComponent<Button>();
		btnReserve.onClick.RemoveAllListeners();
		btnReserve.onClick.AddListener(
			() =>
			{
				playoutOpResult(0, new List<uint>());
			}
		);

		Button btnPlayout = imgPlayoutTips.transform.Find("btn_playout").GetComponent<Button>();
		btnPlayout.onClick.RemoveAllListeners();
		btnPlayout.onClick.AddListener(
			() =>
			{
				List<uint> willPlayout;
				int playoutCardType;
				if (!getWillPlayoutCards(out willPlayout, out playoutCardType))
				{
					return;
				}
				playoutOpResult(playoutCardType, willPlayout);
			}
		);
	}

	private void handleCurPlayerStateChanged(int entityID)
	{
		Account acc = KBEngineApp.app.player() as Account;
		if (acc.id != entityID)
		{
			return;
		}

		switch (acc.curState)
		{
			case StateDef.RoomNoPlayWait:
			case StateDef.RoomPrepare:
				playerPrepareOrNot(entityID);
				break;

			case StateDef.JiaoDizhu:
			case StateDef.QiangDizhu:
				playerJiaopai(entityID);
				break;

			case StateDef.FirstPlayout:
			case StateDef.FollowPlayout:
				playerPlayoutCard(entityID);
				break;
		}
	}

	public void onCurStateChanged(int entityID, UInt32 oldState)
	{
		handleCurPlayerStateChanged(entityID);

		Entity entity;
		if (!KBEngineApp.app.entities.TryGetValue(entityID, out entity))
		{
			return;
		}
		Account accEntity = entity as Account;

		for (int i = 1; i <= ConstDef.PlayCardNeedPlayerNum; ++i)
		{
			Int64 curEntityID = transform.Find(String.Format("img_player_info{0:D0}", i)).GetComponent<CustomData>().int64Data;
			if (curEntityID != entityID)
			{
				continue;
			}

			Image imgState = transform.Find(String.Format("img_player_info{0:D0}/img_state", i)).GetComponent<Image>();
			imgState.sprite = Resources.Load(String.Format("state/state{0:D0}", accEntity.curState), typeof(Sprite)) as Sprite;

			Text txtSurplusCardNum = transform.Find(String.Format("img_player_info{0:D0}/txt_surplus_card_num", i)).GetComponent<Text>();
			txtSurplusCardNum.text = Convert.ToString(accEntity.handCardNum);

			break;
		}
	}

	public void onRoomNetMsg(List<object> listMsg)
	{
		int msgID = Convert.ToInt32(listMsg[0]);
		if (msgID != MsgDef.CELL2CLIENT_ROOM_MSG)
		{
			return;
		}

		Int32 subMsg = Convert.ToInt32(listMsg[1]);
		switch (subMsg)
		{
			case RoomDef.SUBMSG_PREPARE:
				onNetPrepareResult(listMsg);
				break;
		}
	}
}
